﻿using FairyGUI;
using System;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// Helper for drag and drop.
/// 这是一个提供特殊拖放功能的功能类。与GObject.draggable不同，拖动开始后，他使用一个替代的图标作为拖动对象。
/// 当玩家释放鼠标/手指，目标组件会发出一个onDrop事件。
/// </summary>
public class DragDropManagerEx
{
    private GComponent _agent;
    private object _sourceData;
    private GObject _source;

    private static DragDropManagerEx _inst;
    public static DragDropManagerEx inst
    {
        get
        {
            if (_inst == null)
                _inst = new DragDropManagerEx();
            return _inst;
        }
    }

    public DragDropManagerEx()
    {
        _agent = UIPackage.CreateObject("Main", "text_drag").asCom;
        _agent.gameObjectName = "DragDropAgent";
        _agent.SetHome(GRoot.inst);
        _agent.touchable = false;//important
        _agent.draggable = true;
        _agent.SetSize(100, 100);
        _agent.SetPivot(0.5f, 0.5f, true);
        //_agent.align = AlignType.Center;
        //_agent.verticalAlign = VertAlignType.Middle;
        _agent.sortingOrder = int.MaxValue;
        _agent.onDragEnd.Add(__dragEnd);
    }

    /// <summary>
    /// Is dragging?
    /// 返回当前是否正在拖动。
    /// </summary>
    public bool dragging
    {
        get { return _agent.parent != null; }
    }

    /// <summary>
    /// Start dragging.
    /// 开始拖动。
    /// </summary>
    /// <param name="source">Source object. This is the object which initiated the dragging.</param>
    /// <param name="icon">Icon to be used as the dragging sign.</param>
    /// <param name="sourceData">Custom data. You can get it in the onDrop event data.</param>
    /// <param name="touchPointID">Copy the touchId from InputEvent to here, if has one.</param>
    public void StartDrag(GObject source, string text, object sourceData, int touchPointID = -1)
    {
        if (_agent.parent != null)
            return;

        _sourceData = sourceData;
        _source = source;
        _agent.GetChildAt(0).asTextField.text = text;
        GRoot.inst.AddChild(_agent);
        _agent.xy = GRoot.inst.GlobalToLocal(Stage.inst.GetTouchPosition(touchPointID));
        _agent.y += 22;
        _agent.StartDrag(touchPointID);
    }

    /// <summary>
    /// Cancel dragging.
    /// 取消拖动。
    /// </summary>
    public void Cancel()
    {
        if (_agent.parent != null)
        {
            _agent.StopDrag();
            GRoot.inst.RemoveChild(_agent);
            _sourceData = null;
        }
    }

    private void __dragEnd(EventContext evt)
    {
        if (_agent.parent == null) //cancelled
            return;

        GRoot.inst.RemoveChild(_agent);

        object sourceData = _sourceData;
        GObject source = _source;
        _sourceData = null;
        _source = null;

        GObject obj = GRoot.inst.touchTarget;
        while (obj != null)
        {
            if (obj.hasEventListeners("onDrop"))
            {
                obj.RequestFocus();
                obj.DispatchEvent("onDrop", sourceData, source);
                return;
            }
            obj = obj.parent;
        }
    }
}